home *** CD-ROM | disk | FTP | other *** search
-
- !------------------------------------------------------
- ! Monster control script !
- !
- ! When a fight starts, entry point 0 is invoked to
- ! spread out the monster group, and then entry point 1
- ! is invoked to allow each of the monsters to move
- ! during the fight itself.
- !------------------------------------------------------
-
- !
- ! = = = Position Monsters = = =
- !
- ! When this entry point is invoked, the first NPC
- ! is the leader, and the rest of the NPCs (if any)
- ! are followers and have:
- ! a) Half the stats (hp, str, aim, etc.) of the first one
- ! b) The graphics block from NPC.BLOCK2
- ! c) The name associated with the graphics block (not the
- ! first NPC's name.
- ! d) All occupy the same exact X/Y position
- !
- ! What is left to do is to position them in an
- ! intelligent manner for the fight.
- !
-
- :@0
-
- if not fighting then
- writeln( "BUG: FIGHTING script called when not fighting! " );
- stop;
- endif;
-
- L0 = sgn( npc.x - player.x );
- if L0 = 0 then L0 = -1; endif;
- L1 = sgn( npc.y - player.y );
- if L1 = 0 then L1 = 1; endif;
- L2 = 0;
- L4 = L0; ! Start Here !
- L5 = 0;
- foreach NPC do
- if npc.index > 0 then ! A follower !
- :AGAIN
- inc(L2);
- if L2 > 32 then
- stop; ! Give Up. Leave all other NPCs where they are !
- endif;
- gosub CHK_POS;
- if L5 <> L1 then
- inc( L5, L1 );
- else
- L5 = 0;
- dec( L4, L0 );
- if L4 = 0 then
- inc( L0, sgn(L0) );
- inc( L1, sgn(L1) );
- L4 = L0;
- endif;
- endif;
- if npc.x <> L11 or npc.y <> L12 goto :AGAIN;
- endif;
- :NEXTONE
- endfor;
- stop;
-
- :CHK_POS
- L11 = npc.x + L4;
- L12 = npc.y + L5;
- if L11 < 0 or L12 < 0 or L11 >= world.x or L12 >= world.y then
- return;
- endif;
- foreach player do
- if player.x = L11 and player.y = L12 then
- return;
- endif;
- endfor;
- L10 = world.density(L11,L12);
- if npc.class = WATER_MONSTER then
- if L10 = LOW_WATER or L10 = ROUGH_WATER or L10 = DEEP_WATER then
- npc.x = L11; npc.y = L12;
- endif;
- elsif npc.class = SPOOK_MONSTER then
- if L10 <> LOW_WATER and L10 <> ROUGH_WATER and L10 <> DEEP_WATER then
- npc.x = L11; npc.y = L12;
- endif;
- else
- ! LAND and CAVE types
- if L10 = FLAT or L10 = ROUGH or L10 = VERY_ROUGH or
- L10 = SWAMP or L10 = DESERT or L10 = SNOW then
- npc.x = L11; npc.y = L12;
- endif;
- endif;
- return;
-
- !
- ! = = = Move Monsters = = =
- !
- :@1
-
- if not fighting then
- writeln( "BUG: FIGHTING script called when not fighting! " );
- stop;
- endif;
-
- !
- ! Now handle each monster, one at a time
- !
- foreach NPC do
- frame( npc.x, npc.y, SYS_FRAME );
- stats( npc );
- write( npc.name );
- if npc.hp = 1 then
- writeln( " is unconscious.." );
- elsif npc.paralyzed then
- writeln( " is paralyzed.." );
- dec( npc.paralyzed );
- elsif npc.scared then
- writeln( " is scared stiff.." );
- dec( npc.scared );
- elsif npc.confused then
- writeln( " is confused.." );
- dec( npc.confused );
- else
- ! Setup...
- if npc.weapon.count then
- L4 = npc.weapon.class;
- L5 = npc.weapon.range;
- L6 = npc.weapon.ammoneeded;
- L7 = npc.weapon.damage;
- else
- L4 = BLUNT;
- L5 = 1;
- L6 = 0;
- L7 = 1;
- endif;
- if L4 = MISSILE then
- for L10 = 0 to 15 do
- setbp( npc, L10 );
- if npc.bp.count then
- if npc.bp.type = AMMO and npc.bp.ammotype = L6 then
- if npc.bp.count < 255 then
- ! Count of 255 means you never run out !
- dec(npc.bp.count);
- endif;
- L5 = max( L5, npc.bp.range ); ! Use ammo's range if higher !
- inc( L7, npc.bp.damage ); ! If ammunition causes extra damage !
- L6 = npc.bp.index; ! Keep AMMO's BP here !
- goto FOUND_AMMO;
- endif;
- endif;
- endfor;
- L4 = BLUNT;
- L5 = 1;
- L6 = 0;
- L7 = 1;
- :FOUND_AMMO
- endif;
-
- ! For contact weapons, STRENGTH adjusts damage estimate !
- if L4 = BLUNT or L4 = EDGED then
- inc( L7, adjustments( npc.str ) );
- endif;
-
- !
- ! We have a weapon and a range, now find a player..
- !
- L1 = -1;
- L2 = 999;
- foreach player do
- if player.hp > 0 then
- ! Distance to this player
- L3 = max(abs(player.x - npc.x),abs(player.y - npc.y));
- ! Find the closest player, in case all are too far away.
- if L3 < L2 then
- L2 = L3; L1 = player.index;
- endif;
- if L3 <= L5 then ! Found one close enough !
- ! For MISSILE weapons, hit 50% adjusted by AIM
- if L4 = MISSILE then
- ! For missile weapon, hit 5 out of 10, adjusted by AIM !
- if random( 10 ) + adjustments( npc.aim ) < 5 then
- writeln( " missed.." );
- voice( "BadAim", 1000 );
- goto NEXT_MONSTER;
- else
- goto HIT_PLAYER;
- endif;
- else
- ! For NON-MISSILE weapons, hit 70% adjusted up by
- ! the NPCs dexerity and down by the PLAYER's.
- if random(10) +
- adjustments(npc.dex) -
- adjustments(player.dex) < 3 then
- writeln( " missed.." );
- voice( "Swish", 1000 );
- goto NEXT_MONSTER;
- else
- goto HIT_PLAYER;
- endif;
- endif;
- endif;
- endif;
- endfor;
-
- !
- ! None within range, move towards the closest one
- !
- s0 = " is blocked.";
- if L1 >= 0 then
-
- ! Move one step towards the closest player (L1)
- group.current = L1;
- L1 = npc.x + sgn(player.x - npc.x);
- L2 = npc.y + sgn(player.y - npc.y);
-
- ! Don't step on another player !
- foreach player do
- if player.x = L1 and player.y = L2 then
- writeln( s0 );
- goto NEXT_MONSTER;
- endif;
- endfor;
- ! Or another monster
- L3 = npc.index; ! Save the NPC index !
- foreach npc do
- if npc.x = L1 and npc.y = L2 then
- npc.index = L3; ! Restore the NPC index !
- writeln( s0 );
- goto NEXT_MONSTER;
- endif;
- endfor;
- ! Ok to move...
- npc.index = L3; ! Restore the NPC index !
- !
- L3 = world.density(L1,L2);
- if npc.class = WATER_MONSTER then
- if L3 = LOW_WATER or L3 = ROUGH_WATER or L3 = DEEP_WATER then
- npc.x = L1; npc.y = L2;
- s0 = " moved.";
- endif;
- elsif npc.class = SPOOK_MONSTER then
- if L3 <> LOW_WATER and L3 <> ROUGH_WATER and L3 <> DEEP_WATER then
- npc.x = L1; npc.y = L2;
- s0 = " moved.";
- endif;
- else
- ! LAND and CAVE types
- if L3 = FLAT or L3 = ROUGH or L3 = VERY_ROUGH or
- L3 = SWAMP or L3 = DESERT or L3 = SNOW then
- npc.x = L1; npc.y = L2;
- s0 = " moved.";
- endif;
- endif;
- endif;
- writeln( s0 );
- goto NEXT_MONSTER;
-
- :HIT_PLAYER
- if player.ac then ! Armor Class protects the PLAYER !
- L8 = random( player.ac+1 ); ! Player's armor
- if L8 >= L7 then
- writeln( " hits ", player.name, " but does not damage." );
- voice( "Clank", 1000 );
- goto NEXT_MONSTER;
- endif;
- dec( L7, L8 ); ! Reduce damage by L8 amount !
- endif;
- if player.hp > L7 then
- writeln( " hits ", player.name, " for ", L7, " points of damage" );
- dec( player.hp, L7 );
- on random(3) goto :V1, :V2, :V3;
- :V1 voice( "Argh", 1000 ); goto NEXT_MONSTER;
- :V2 voice( "Ouch", 1000 ); goto NEXT_MONSTER;
- :V3 voice( "Whoosh", 1000 ); goto NEXT_MONSTER;
- else
- voice( "Argh", 1000 );
- write( " killed ", player.name, "!" );
- L7 = player.hp;
- player.hp = 0;
- endif;
-
- :NEXT_MONSTER
-
- endif;
- if sound then
- wait(0); ! Wait for sounds to finish playing !
- ! Note that wait(0) waits forever if sound is off !
- endif;
- wait(1); ! Now wait for one second to slow down !
- frame( npc.x, npc.y, -SYS_FRAME );
-
- endfor;
-
- STOP;
-